package com.samehope.ar.service.impl;

import com.samehope.ar.constant.DelFlagEnum;
import com.samehope.ar.dto.ItemAddParam;
import com.samehope.ar.dto.ItemChildParam;
import com.samehope.ar.dto.ItemTypeAddParam;
import com.samehope.ar.dto.ItemUpdateParam;
import com.samehope.ar.entity.PatrolItem;
import com.samehope.ar.entity.PatrolItemChild;
import com.samehope.ar.entity.PatrolItemType;
import com.samehope.ar.mapper.PatrolItemMapper;
import com.samehope.ar.service.IPatrolItemChildService;
import com.samehope.ar.service.IPatrolItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.samehope.ar.service.IPatrolItemTypeService;
import com.samehope.ar.util.SessionUtil;
import com.samehope.ar.util.TreeUtils;
import com.samehope.ar.vo.FormSelectVO;
import com.samehope.ar.vo.ItemDetailVO;
import com.samehope.ar.vo.TreeDataVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static java.time.LocalDateTime.now;

/**
 * <p>
 * 巡检项 服务实现类
 * </p>
 *
 * @author Zhang Luo
 * @since 2019-12-23
 */
@Service
public class PatrolItemServiceImpl extends ServiceImpl<PatrolItemMapper, PatrolItem> implements IPatrolItemService {

    @Autowired
    private IPatrolItemChildService itemChildService;

    @Autowired
    private IPatrolItemTypeService itemTypeService;

    /**
     * 根据巡检项分类查询巡检项
     * @param itemTypeId
     * @return
     */
    @Override
    public List<PatrolItem> findByItemType(Long itemTypeId) {
        return this.baseMapper.findByProjectAndItemType(SessionUtil.getProjectId(), itemTypeId);
    }

    /**
     * 添加检查项
     * @param param
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long add(ItemAddParam param) {

        Long itemTypeId = this.checkAndGetItemType(param.getItemTypeId(), param.getItemTypeName());
        param.setItemTypeId(itemTypeId);
        PatrolItem patrolItem;
        if (param.getSubjectType() == 0 || param.getSubjectType() == 2) {
            // 填空题 或者 判断题
            patrolItem = new PatrolItem();
            this.saveItem(patrolItem, param);

        } else if (param.getSubjectType() == 1) {
            List<ItemChildParam> itemChild = param.getItemChild();
            // 选择题
            if (itemChild == null || itemChild.size() == 0) {
                throw new IllegalArgumentException("缺少选择项");
            }

            // 保存巡检项
            patrolItem = new PatrolItem();
            this.saveItem(patrolItem, param);

            // 保存子项
            this.saveChoiceChildren(patrolItem, itemChild);
        } else if (param.getSubjectType() == 3) {
            // 范围题
            List<ItemChildParam> itemChild = param.getItemChild();
            if (itemChild == null || itemChild.size() != 1) {
                throw new IllegalArgumentException("请输入正确的范围值");
            }

            // 保存巡检项
            patrolItem = new PatrolItem();
            this.saveItem(patrolItem, param);

            // 保存子项
            this.saveValueScopeChildren(patrolItem, itemChild);
        } else {
            throw new IllegalArgumentException("问题类型无法识别");
        }
        return patrolItem.getId();
    }

    /**
     * 获取巡检项视图对象
     * @param itemId
     * @return
     */
    @Override
    public ItemDetailVO itemDetail(Long itemId) {
        return this.baseMapper.findDetailByProjectAndItem(SessionUtil.getProjectId(), itemId);
    }

    /**
     * 删除巡检项
     * @param itemId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteItem(Long itemId) {
        PatrolItem item = this.baseMapper.findByProjectAndItem(SessionUtil.getProjectId(), itemId);

        if (item == null) {
            throw new IllegalArgumentException("巡检项不存在");
        }

        LocalDateTime now = now();

        item.setDelFlag(DelFlagEnum.DELETED.getCode());
        item.setUpdateBy(SessionUtil.getUserId());
        item.setUpdateDate(now);
        this.updateById(item);

        this.deleteChildren(itemId);
    }

    /**
     * 删除子项
     * @param itemId
     */
    private void deleteChildren(Long itemId) {
        List<PatrolItemChild> children = itemChildService.findByItem(itemId);
        if (children.size() > 0) {
            children.forEach(e -> {
                e.setDelFlag(DelFlagEnum.DELETED.getCode());
                e.setUpdateBy(SessionUtil.getUserId());
                e.setUpdateDate(now());
            });
            itemChildService.updateBatchById(children);
        }
    }

    /**
     * 保存选择类型子项
     * @param patrolItem
     * @param itemChild
     */
    private void saveChoiceChildren(PatrolItem patrolItem, List<ItemChildParam> itemChild) {
        List<PatrolItemChild> children = new ArrayList<>();
        for (int i = 0; i < itemChild.size(); i++) {
            ItemChildParam itemChildParam = itemChild.get(i);
            if (StringUtils.isBlank(itemChildParam.getChoiceItem())) {
                throw new IllegalArgumentException("选择项不能为空");
            }
            if (itemChildParam.getTrueOrFalse() == null) {
                throw new IllegalArgumentException("是否正常值不能为空");
            }
            PatrolItemChild child = new PatrolItemChild();
            child.setCompanyId(SessionUtil.getCompanyId());
            child.setPatrolItemId(patrolItem.getId());
            child.setChoiceItem(itemChildParam.getChoiceItem());
            child.setTrueOrFalse(itemChildParam.getTrueOrFalse());
            child.setCreateBy(SessionUtil.getUserId());
            child.setCreateDate(now());
            children.add(child);
        }

        itemChildService.saveBatch(children);
    }

    /**
     * 保存值范围的子项
     * @param patrolItem
     * @param itemChild
     */
    private void saveValueScopeChildren(PatrolItem patrolItem, List<ItemChildParam> itemChild) {
        List<PatrolItemChild> children = new ArrayList<>();
        for (int i = 0; i < itemChild.size(); i++) {
            ItemChildParam itemChildParam = itemChild.get(i);
            if (itemChildParam.getStandardValue() == null) {
                throw new IllegalArgumentException("标准值不能为空");
            }
            if (itemChildParam.getUpperLimit() == null) {
                throw new IllegalArgumentException("上限值不能为空");
            }
            if (itemChildParam.getLowerLimit() == null) {
                throw new IllegalArgumentException("下限值不能为空");
            }
            PatrolItemChild child = new PatrolItemChild();
            child.setCompanyId(SessionUtil.getCompanyId());
            child.setPatrolItemId(patrolItem.getId());
            child.setStandardValue(itemChildParam.getStandardValue());
            child.setUpperLimit(itemChildParam.getUpperLimit());
            child.setLowerLimit(itemChildParam.getLowerLimit());
            child.setCreateBy(SessionUtil.getUserId());
            child.setCreateDate(now());
            children.add(child);
        }

        itemChildService.saveBatch(children);
    }

    /**
     * 更新巡检项
     * @param param
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateItem(ItemUpdateParam param) {

        Long itemTypeId = this.checkAndGetItemType(param.getItemTypeId(), param.getItemTypeName());
        param.setItemTypeId(itemTypeId);

        PatrolItem patrolItem = this.baseMapper.findByProjectAndItem(SessionUtil.getProjectId(), param.getItemId());
        if (patrolItem == null) {
            throw new IllegalArgumentException("巡检项不存在");
        }

        // 清空之前的内容
        this.deleteChildren(patrolItem.getId());

        if (param.getSubjectType() == 0 || param.getSubjectType() == 2) {
            // 填空题 或者 判断题
            this.updateItem(patrolItem, param);

        } else if (param.getSubjectType() == 1) {
            List<ItemChildParam> itemChild = param.getItemChild();
            // 选择题
            if (itemChild == null || itemChild.size() == 0) {
                throw new IllegalArgumentException("缺少选择项");
            }

            // 保存巡检项
            this.updateItem(patrolItem, param);

            // 保存子项
            this.saveChoiceChildren(patrolItem, itemChild);
        } else if (param.getSubjectType() == 3) {
            // 范围题
            List<ItemChildParam> itemChild = param.getItemChild();
            if (itemChild == null || itemChild.size() != 1) {
                throw new IllegalArgumentException("请输入正确的范围值");
            }

            // 保存巡检项
            this.updateItem(patrolItem, param);

            // 保存子项
            this.saveValueScopeChildren(patrolItem, itemChild);
        } else {
            throw new IllegalArgumentException("问题类型无法识别");
        }
    }

    /**
     * 检查和获取巡检项分类ID
     * @param itemTypeId
     * @param itemTypeName
     * @return
     */
    private Long checkAndGetItemType(Long itemTypeId, String itemTypeName) {

        if (itemTypeName != null) {
            PatrolItemType itemType = itemTypeService.findTypeByTypeName(itemTypeName);
            if (itemType == null) {
                ItemTypeAddParam itemTypeAddParam = new ItemTypeAddParam();
                itemTypeAddParam.setName(itemTypeName);
                itemTypeId = itemTypeService.add(itemTypeAddParam);
            } else {
                itemTypeId = itemType.getId();
            }
        }

        return itemTypeId;
    }

    /**
     * 查询巡检项树结构
     * @param condition
     * @return
     */
    @Override
    public List<TreeDataVO> getItemTree(String condition) {
        List<TreeDataVO> tree = this.baseMapper.findItemTreeByProjectAndCondition(SessionUtil.getProjectId(), condition);
        TreeUtils.setLevel(tree, 1);
        TreeUtils.setId(tree);
        return tree;
    }

    /**
     * 巡检项下拉菜单接口
     * @return
     */
    @Override
    public List<FormSelectVO> itemsForSelect() {
        return this.baseMapper.itemsForSelectByProject(SessionUtil.getProjectId());
    }

    /**
     * 根据点位查询巡检项树结构
     * @param pointId
     * @return
     */
    @Override
    public List<TreeDataVO> getItemTreeByPointId(Long pointId) {
        List<TreeDataVO> tree = this.baseMapper
                .findItemTreeByProjectIdAndPointId(SessionUtil.getProjectId(), pointId);
        TreeUtils.setLevel(tree, 1);
        TreeUtils.setId(tree);
        return tree;
    }

    /**
     * 添加巡检项
     * @param patrolItem
     * @param param
     */
    private void saveItem(PatrolItem patrolItem, ItemAddParam param) {
        patrolItem.setCompanyId(SessionUtil.getCompanyId());
        patrolItem.setProjectId(SessionUtil.getProjectId());
        patrolItem.setCreateBy(SessionUtil.getUserId());
        patrolItem.setCreateDate(now());
        patrolItem.setIsPhoto(param.getIsPhoto());
        patrolItem.setIsRemark(param.getIsRemark());
        patrolItem.setIsVideo(param.getIsVideo());
        patrolItem.setPatrolItemName(param.getItemName());
        patrolItem.setPatrolItemDesc(param.getItemDesc());
        patrolItem.setPatrolItemTypeId(param.getItemTypeId());
        patrolItem.setPatrolItemNo(param.getItemNo());
        patrolItem.setSubjectType(param.getSubjectType());
        patrolItem.setTitle(param.getTitle());
        patrolItem.setRemarks(param.getRemarks());
        patrolItem.setVideoUrl(param.getVideoUrl());

        this.save(patrolItem);
    }

    /**
     * 更新巡检项
     * @param patrolItem
     * @param param
     */
    private void updateItem(PatrolItem patrolItem, ItemUpdateParam param) {
        patrolItem.setCompanyId(SessionUtil.getCompanyId());
        patrolItem.setProjectId(SessionUtil.getProjectId());
        patrolItem.setUpdateBy(SessionUtil.getUserId());
        patrolItem.setUpdateDate(now());
        patrolItem.setIsPhoto(param.getIsPhoto());
        patrolItem.setIsRemark(param.getIsRemark());
        patrolItem.setIsVideo(param.getIsVideo());
        patrolItem.setVideoUrl(param.getVideoUrl());
        patrolItem.setPatrolItemName(param.getItemName());
        patrolItem.setPatrolItemDesc(param.getItemDesc());
        patrolItem.setPatrolItemTypeId(param.getItemTypeId());
        patrolItem.setPatrolItemNo(param.getItemNo());
        patrolItem.setSubjectType(param.getSubjectType());
        patrolItem.setTitle(param.getTitle());
        patrolItem.setRemarks(param.getRemarks());

        this.updateById(patrolItem);
    }

}
